/* PR c/102989 */
/* { dg-do run { target bitint } } */
/* { dg-options "-std=c23 -pedantic-errors" } */
/* { dg-skip-if "" { ! run_expensive_tests }  { "*" } { "-O0" "-O2" } } */
/* { dg-skip-if "" { ! run_expensive_tests } { "-flto" } { "" } } */

int expected;

__attribute__((noipa)) void
test (int x, int y, int z)
{
  (void) x;
  (void) y;
  if (z != expected)
    __builtin_abort ();
}

#if __BITINT_MAXWIDTH__ >= 135
__attribute__((noipa)) void
test_135 (_BitInt(135) a)
{
  switch (a)
    {
    case -33841133710wb:
      test (1, 2, 1); break;
    case -55283508608004252890371630137wb:
      test (2, 3, 2); break;
    case -1065119162618253595246332535wb:
      test (3, 4, 3); break;
    case 265225687803630460135wb:
      test (4, 5, 4); break;
    case 12802219454007328327057691wb:
      test (5, 6, 5); break;
    case -59157301wb:
      test (6, 7, 6); break;
    case 28029296819738wb:
      test (7, 8, 7); break;
    case 23771967952817687922824184198772908114wb:
      test (8, 9, 8); break;
    case -528wb:
      test (10, 9, 9); break;
    case -21743705968wb:
      test (11, 8, 10); break;
    case 3761322442803929370621734404255158wb:
      test (12, 7, 11); break;
    case 7581882536870984828946588790215963wb:
      test (13, 6, 12); break;
    case -3601335158354600803149652143011wb:
      test (14, 5, 13); break;
    case 104802210847691888333394846958wb:
      test (15, 4, 14); break;
    case 145823237253137988087297wb:
      test (16, 3, 15); break;
    case 3871725619091wb:
      test (17, 2, 16); break;
    case -480987385702wb:
      test (18, 1, 17); break;
    case -1084968414543030wb:
      test (19, 0, 18); break;
    case -12928976wb:
      test (20, -1, 19); break;
    case -268774wb:
      test (21, -2, 20); break;
    case 532464351235328336949014678wb:
      test (22, -3, 21); break;
    case -1145290618187237284790705482290160wb:
      test (23, -4, 22); break;
    case -249459466889744wb:
      test (24, -5, 23); break;
    case -1403065236wb:
      test (25, 1, 24); break;
    case -25456270573862478377606wb:
      test (26, 2, 25); break;
    case 33340794611915791wb:
      test (27, 3, 26); break;
    case -674079586163272813wb:
      test (28, 4, 27); break;
    case -41952758959718119236303556590897001668wb:
      test (29, 5, 28); break;
    case 2947453415wb:
      test (30, 6, 29); break;
    case -677wb:
      test (31, 7, 30); break;
    case -463646803422851872253575745194919wb:
      test (32, 8, 31); break;
    case -71367919591514155952975401251963194wb:
      test (33, 7, 32); break;
    case -14346961913818709867962386609601wb:
      test (34, 6, 33); break;
    case 690wb:
      test (35, 5, 34); break;
    default:
      test (36, 4, 35); break;
      break;
    }
}
#endif

#if __BITINT_MAXWIDTH__ >= 192
__attribute__((noipa)) int
test_192 (unsigned _BitInt(192) a)
{
  switch (a)
    {
    case 1505160143063006983093195408894239764415303566721254616896uwb + 48:
    case 1505160143063006983093195408894239764415303566721254616896uwb + 49:
    case 1505160143063006983093195408894239764415303566721254616896uwb + 50:
    case 1505160143063006983093195408894239764415303566721254616896uwb + 51:
    case 1505160143063006983093195408894239764415303566721254616896uwb + 52:
    case 1505160143063006983093195408894239764415303566721254616896uwb + 53:
    case 1505160143063006983093195408894239764415303566721254616896uwb + 54:
    case 1505160143063006983093195408894239764415303566721254616896uwb + 55:
    case 1505160143063006983093195408894239764415303566721254616896uwb + 56:
    case 1505160143063006983093195408894239764415303566721254616896uwb + 57:
    case 1505160143063006983093195408894239764415303566721254616896uwb + 65:
    case 1505160143063006983093195408894239764415303566721254616896uwb + 66:
    case 1505160143063006983093195408894239764415303566721254616896uwb + 67:
    case 1505160143063006983093195408894239764415303566721254616896uwb + 68:
    case 1505160143063006983093195408894239764415303566721254616896uwb + 69:
    case 1505160143063006983093195408894239764415303566721254616896uwb + 70:
      return 1;
    default:
      return 0;
    }
}
#endif

#if __BITINT_MAXWIDTH__ >= 574
__attribute__((noipa)) void
test_574 (unsigned _BitInt(574) a)
{
  switch (a)
    {
    case 6286965391667017312339071741838237504698922691411382973783611300502970166307629280084891246uwb:
      test (22, -3, 1); break;
    case 6286965391667017312339071741838237504698922691411382973783611300502970166307629280084891247uwb:
      test (23, -4, 2); break;
    case 6286965391667017312339071741838237504698922691411382973783611300502970166307629280084891248uwb:
      test (24, -5, 3); break;
    case 6286965391667017312339071741838237504698922691411382973783611300502970166307629280084891249uwb:
      test (25, 1, 4); break;
    case 6286965391667017312339071741838237504698922691411382973783611300502970166307629280084891250uwb:
      test (26, 2, 5); break;
    case 6286965391667017312339071741838237504698922691411382973783611300502970166307629280084891251uwb:
      test (27, 3, 6); break;
    case 6286965391667017312339071741838237504698922691411382973783611300502970166307629280084891257uwb:
      test (28, 4, 7); break;
    default:
      test (29, 5, 8); break;
      break;
    }
}
#endif

#if __BITINT_MAXWIDTH__ >= 575
__attribute__((noipa)) void
test_575 (_BitInt(575) a)
{
  switch (a)
    {
    case 57158236877324191282832099954551676419657688516114213070568173374483038461911230482096734270573673572006270803057167488583704wb:
      test (1, 2, 1); break;
    case 55932752002978259755258693759201176077252755664748wb:
      test (2, 3, 2); break;
    case -4218363291370143377367234486177453689054229233132334373089588356145503900632432151470684730299990106009156255994430506676467506300235609892554834254413957477779209219867825wb:
      test (3, 4, 3); break;
    case -19380856704203460544565443028wb:
      test (4, 5, 4); break;
    case 37691457600250454282496246135038751153145234859661859831059667050412054918743986000946778819692986258358820458161034213280wb:
      test (5, 6, 5); break;
    case 827003152758795459486819489974390601625339063627401335603123746581523657253393870961575744071183196915560771288079061574485309986042624106685495948664669wb:
      test (6, 7, 6); break;
    case 2001882657256786505981789524889669355393757203160978wb:
      test (7, 8, 7); break;
    case 2273951349206310803215316642428483249009583047771549wb:
      test (8, 9, 8); break;
    case -63640037492105525397657594648433413082358686497544854829581174487203243151113011293858381773246wb:
      test (10, 9, 9); break;
    case -5043989193130150016980754467018673356423436330428309162407512361831163237wb:
      test (11, 8, 10); break;
    case -86904413785414524864201428752820860524832869110219388825241400306401wb:
      test (12, 7, 11); break;
    case -7159581406wb:
      test (13, 6, 12); break;
    case -430416863734662045942802859497964wb:
      test (14, 5, 13); break;
    case -282099469984391093781566wb:
      test (15, 4, 14); break;
    case 259191242782270578340350840252447902477249511321245827805053349778984004438373803812874430619356951005300429wb:
      test (16, 3, 15); break;
    case -17427431700557396203431wb:
      test (17, 2, 16); break;
    case -324305733281944621534wb:
      test (18, 1, 17); break;
    case 39167932287702074309519944575154814029176054304655900600154735991016090154633448789399330wb:
      test (19, 0, 18); break;
    case 198828227576458371467364915441164050473274232622009526563856039032wb:
      test (20, -1, 19); break;
    case 7522018863556878842079508104211164618555wb:
      test (21, -2, 20); break;
    case -6286965391667017312339071741838237504698922691411382973783611300502970166307629280084891246wb:
      test (22, -3, 21); break;
    case -6286965391667017312339071741838237504698922691411382973783611300502970166307629280084891247wb:
      test (23, -4, 22); break;
    case -6286965391667017312339071741838237504698922691411382973783611300502970166307629280084891248wb:
      test (24, -5, 23); break;
    case -6286965391667017312339071741838237504698922691411382973783611300502970166307629280084891249wb:
      test (25, 1, 24); break;
    case -6286965391667017312339071741838237504698922691411382973783611300502970166307629280084891250wb:
      test (26, 2, 25); break;
    case -6286965391667017312339071741838237504698922691411382973783611300502970166307629280084891251wb:
      test (27, 3, 26); break;
    case 25232715496072790939146860623749108256506615788345509143038026592127702780903347954226870163752427434085269890371577229233150314692259399042327414965711510629wb:
      test (28, 4, 27); break;
    case 21376200838998904075479297127185224975235208544658573531790808467114261325514834503383673531634166234wb:
      test (29, 5, 28); break;
    case -12950763061001084589012736558965423479147155000678492177259830314151681149963956790935448632739537613359984550457633150573373wb:
      test (30, 6, 29); break;
    case -2588834879960231787797472372536501710262304078735816335394876043103825991870347510560085648304946wb:
      test (31, 7, 30); break;
    case -2701643349985817058465875459099740236751728453427684wb:
      test (32, 8, 31); break;
    case 5836201004021438163265930908885473220627459728279406489088525555799694670629946003808237930825748wb:
      test (33, 7, 32); break;
    case 44108809764408326456612205445124618284924483635588993217673301668963284129265963564132943970751645671455967029559660507196902756491684232894669648136319146730wb:
      test (34, 6, 33); break;
    case 2296104972770686523043774188826290903188890257660332269411533641473619626906874515994186550107564291006924533677263136416982312042wb:
      test (35, 5, 34); break;
    case 2194074380385385359486226752708738wb:
      test (36, 4, 35); break;
    case 538995045833371297308662695915673724930785814100527903453604wb:
      test (37, 3, 36); break;
    case 2085626377217975761550063150555904902911153438008474368944585344266562733501648381wb:
      test (38, 2, 37); break;
    case -33688835949886075020354777490957071wb:
      test (39, 1, 38); break;
    case 1391419408329070356813886663340861253838000363084420822349730519562112746630131027735880100996653wb:
      test (40, 0, 39); break;
    default:
      test (41, -1, 40); break;
      break;
    }
}
#endif

int
main ()
{
#if __BITINT_MAXWIDTH__ >= 135
  static _BitInt(135) a_135[] = {
    -33841133710wb,
    -55283508608004252890371630137wb,
    -1065119162618253595246332535wb,
    265225687803630460135wb,
    12802219454007328327057691wb,
    -59157301wb,
    28029296819738wb,
    23771967952817687922824184198772908114wb,
    -528wb,
    -21743705968wb,
    3761322442803929370621734404255158wb,
    7581882536870984828946588790215963wb,
    -3601335158354600803149652143011wb,
    104802210847691888333394846958wb,
    145823237253137988087297wb,
    3871725619091wb,
    -480987385702wb,
    -1084968414543030wb,
    -12928976wb,
    -268774wb,
    532464351235328336949014678wb,
    -1145290618187237284790705482290160wb,
    -249459466889744wb,
    -1403065236wb,
    -25456270573862478377606wb,
    33340794611915791wb,
    -674079586163272813wb,
    -41952758959718119236303556590897001668wb,
    2947453415wb,
    -677wb,
    -463646803422851872253575745194919wb,
    -71367919591514155952975401251963194wb,
    -14346961913818709867962386609601wb,
    690wb
  };
  for (int i = 0; i < 34; ++i)
    {
      expected = i + 1;
      test_135 (a_135[i]);
      expected = 35;
      test_135 (a_135[i] - 1);
      test_135 (a_135[i] + 1);
    }
#endif
#if __BITINT_MAXWIDTH__ >= 192
  if (test_192 (0uwb)
      || test_192 (1505160143063006983093195408894239764415303566721254616896uwb)
      || test_192 (1505160143063006983093195408894239764415303566721254616896uwb + 47)
      || test_192 (1505160143063006983093195408894239764415303566721254616896uwb + 71)
      || test_192 (-1uwb))
    __builtin_abort ();
  for (int i = 48; i <= 70; ++i)
    if (test_192 (1505160143063006983093195408894239764415303566721254616896uwb + i) != (i < 58 || i > 64))
      __builtin_abort ();
#endif
#if __BITINT_MAXWIDTH__ >= 574
  expected = 8;
  test_574 (0uwb);
  test_574 (6286965391667017312339071741838237504698922691411382973783611300502970166307629280084891246uwb - 0x10000000000000000uwb);
  test_574 (6286965391667017312339071741838237504698922691411382973783611300502970166307629280084891245uwb);
  test_574 (6286965391667017312339071741838237504698922691411382973783611300502970166307629280084891258uwb);
  test_574 (6286965391667017312339071741838237504698922691411382973783611300502970166307629280084891246uwb + 0x10000000000000000uwb);
  test_574 (6286965391667017312339071741838237504698922691411382973783611300502970166307629280084891258uwb + 0x10000000000000000uwb);
  for (int i = 0; i <= 11; ++i)
    {
      expected = i == 11 ? 7 : i > 5 ? 8 : i + 1;
      test_574 (6286965391667017312339071741838237504698922691411382973783611300502970166307629280084891246uwb + i);
    }
#endif
#if __BITINT_MAXWIDTH__ >= 575
  static _BitInt(575) a_575[] = {
    57158236877324191282832099954551676419657688516114213070568173374483038461911230482096734270573673572006270803057167488583704wb,
    55932752002978259755258693759201176077252755664748wb,
    -4218363291370143377367234486177453689054229233132334373089588356145503900632432151470684730299990106009156255994430506676467506300235609892554834254413957477779209219867825wb,
    -19380856704203460544565443028wb,
    37691457600250454282496246135038751153145234859661859831059667050412054918743986000946778819692986258358820458161034213280wb,
    827003152758795459486819489974390601625339063627401335603123746581523657253393870961575744071183196915560771288079061574485309986042624106685495948664669wb,
    2001882657256786505981789524889669355393757203160978wb,
    2273951349206310803215316642428483249009583047771549wb,
    -63640037492105525397657594648433413082358686497544854829581174487203243151113011293858381773246wb,
    -5043989193130150016980754467018673356423436330428309162407512361831163237wb,
    -86904413785414524864201428752820860524832869110219388825241400306401wb,
    -7159581406wb,
    -430416863734662045942802859497964wb,
    -282099469984391093781566wb,
    259191242782270578340350840252447902477249511321245827805053349778984004438373803812874430619356951005300429wb,
    -17427431700557396203431wb,
    -324305733281944621534wb,
    39167932287702074309519944575154814029176054304655900600154735991016090154633448789399330wb,
    198828227576458371467364915441164050473274232622009526563856039032wb,
    7522018863556878842079508104211164618555wb,
    -6286965391667017312339071741838237504698922691411382973783611300502970166307629280084891246wb,
    -6286965391667017312339071741838237504698922691411382973783611300502970166307629280084891247wb,
    -6286965391667017312339071741838237504698922691411382973783611300502970166307629280084891248wb,
    -6286965391667017312339071741838237504698922691411382973783611300502970166307629280084891249wb,
    -6286965391667017312339071741838237504698922691411382973783611300502970166307629280084891250wb,
    -6286965391667017312339071741838237504698922691411382973783611300502970166307629280084891251wb,
    25232715496072790939146860623749108256506615788345509143038026592127702780903347954226870163752427434085269890371577229233150314692259399042327414965711510629wb,
    21376200838998904075479297127185224975235208544658573531790808467114261325514834503383673531634166234wb,
    -12950763061001084589012736558965423479147155000678492177259830314151681149963956790935448632739537613359984550457633150573373wb,
    -2588834879960231787797472372536501710262304078735816335394876043103825991870347510560085648304946wb,
    -2701643349985817058465875459099740236751728453427684wb,
    5836201004021438163265930908885473220627459728279406489088525555799694670629946003808237930825748wb,
    44108809764408326456612205445124618284924483635588993217673301668963284129265963564132943970751645671455967029559660507196902756491684232894669648136319146730wb,
    2296104972770686523043774188826290903188890257660332269411533641473619626906874515994186550107564291006924533677263136416982312042wb,
    2194074380385385359486226752708738wb,
    538995045833371297308662695915673724930785814100527903453604wb,
    2085626377217975761550063150555904902911153438008474368944585344266562733501648381wb,
    -33688835949886075020354777490957071wb,
    1391419408329070356813886663340861253838000363084420822349730519562112746630131027735880100996653wb
  };
  for (int i = 0; i < 39; ++i)
    {
      expected = i + 1;
      test_575 (a_575[i]);
      expected = 40;
      if (i < 20 || i >= 25)
	test_575 (a_575[i] - 1);
      if (i <= 20 || i > 25)
	test_575 (a_575[i] + 1);
    }
#endif
}
